package com.ruoyi.dmp.common.util;

import org.apache.commons.lang3.StringUtils;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * Desc: 日期时间工具类
 * Auth: MquanZeng
 * Date: 2020/1/23
 */
public class DmpDateTimeUtil {
    public final static DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    public final static DateTimeFormatter commonCateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    public final static DateTimeFormatter unionDateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
    public final static DateTimeFormatter millSecondDateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");


    public static String getCurrentTime(){
        return LocalDateTime.now().format(commonCateTimeFormatter);
    }

    public static String getCurrentTimeByUnion(){
        return LocalDateTime.now().format(unionDateTimeFormatter);
    }

    public static String getMillSecondTimeStr(){
        return LocalDateTime.now().format(millSecondDateTimeFormatter);
    }

    /**
     * 获取当前年月
     * @return
     */
    public static String getCurYearMonth(String formatStr){
        DateTimeFormatter yearMonthFormat = DateTimeFormatter.ofPattern(formatStr);
        return LocalDateTime.now().format(yearMonthFormat);
    }



    /**
     *  获取今天日期
     * @return
     */
    public static String getToday(){
        return getDayStr(0);
    }

    /**
     * 获取昨天日期
     * @return yyyy-MM-dd
     */
    public static String getYesterday(){
        return getDayStr(-1);
    }

    /**
     * 获取昨天日期
     * @return yyyyMMdd
     */
    public static String getYesterday2(){
        return getDayStr(-1,dateFormatter);
    }

    private static String getDayStr(int plusDays){
        LocalDate localDate = LocalDate.now().plusDays(plusDays);
        return localDate.format(dateFormatter);
    }

    private static String getDayStr(int plusDays,DateTimeFormatter formart){
        LocalDate localDate = LocalDate.now().plusDays(plusDays);
        return localDate.format(formart);
    }

    /**
     * 获取本周周一
     * @param date
     * @return
     */
    public static Date getThisWeekMonday(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        // 获得当前日期是一个星期的第几天
        int dayWeek = cal.get(Calendar.DAY_OF_WEEK);
        if (1 == dayWeek) {
            cal.add(Calendar.DAY_OF_MONTH, -1);
        }
        // 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
        cal.setFirstDayOfWeek(Calendar.MONDAY);
        // 获得当前日期是一个星期的第几天
        int day = cal.get(Calendar.DAY_OF_WEEK);
        // 根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
        cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);
        return cal.getTime();
    }

    /**
     * 获取上周周一
     * @param date
     * @return
     */
    public static Date getLastWeekMonday(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(getThisWeekMonday(date));
        cal.add(Calendar.DATE, -7);
        return cal.getTime();
    }

    /**
     * 获取上周周日
     * @param date
     * @return
     */
    public static Date getLastWeekSunday(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(getThisWeekMonday(date));
        cal.add(Calendar.DATE, -1);
        return cal.getTime();
    }


    /**
     *  获取指定月份的第一天
     * @param year  年
     * @param month 月份，从0到11
     * @return
     */
    public static String getFirstDayOfMonth(String year, String month, String formatStr) {
        //year="2018" month="2"
        Calendar calendar = Calendar.getInstance();
        // 设置时间,当前时间不用设置
        calendar.set(Calendar.YEAR, Integer.parseInt(year));
        calendar.set(Calendar.MONTH, Integer.parseInt(month));
        // System.out.println(calendar.getTime());

        calendar.set(Calendar.DAY_OF_MONTH, 1);
        DateFormat format = new SimpleDateFormat(formatStr);
        return format.format(calendar.getTime()).trim();
    }

    /**
     *  获取指定月份的最后一天
     * @param year  年
     * @param month 月份，从0到11
     * @return
     */
    public static String getLastDayOfMonth(String year, String month, String formatStr) {
        //year="2018" month="2"
        Calendar calendar = Calendar.getInstance();
        // 设置时间,当前时间不用设置
        calendar.set(Calendar.YEAR, Integer.parseInt(year));
        calendar.set(Calendar.MONTH, Integer.parseInt(month));
        // System.out.println(calendar.getTime());

        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));
        DateFormat format = new SimpleDateFormat(formatStr);
        return format.format(calendar.getTime()).trim();
    }


    /**
     *  获取指定月份的第一天
     * @return
     */
    public static String getPointFirstDayOfMonth(String dateStr, String formatStr) throws Exception{
        Calendar calendar = str2Calendar(dateStr, formatStr);
        int year = calendar.get(Calendar.YEAR);//获取年份
        int month=calendar.get(Calendar.MONTH);//获取月份
        return getFirstDayOfMonth(year+"", month+"", formatStr);
    }


    /**
     *  获取指定日期所在月份的最后一天
     * @return
     */
    public static String getPointLastDayOfMonth(String dateStr, String formatStr) throws Exception{
        Calendar calendar = str2Calendar(dateStr, formatStr);
        int year = calendar.get(Calendar.YEAR);//获取年份
        int month=calendar.get(Calendar.MONTH);//获取月份
        return getLastDayOfMonth(year+"", month+"", formatStr);
    }

    /**
     * 日期时间字符串转换为Calendar对象
     * @param dateTimeStr
     * @param formatStr
     * @return
     * @throws ParseException
     */
    public static Calendar str2Calendar(String dateTimeStr, String formatStr) throws ParseException{
        SimpleDateFormat format=new SimpleDateFormat(formatStr);
        Date date=format.parse(dateTimeStr);

        Calendar calendar=Calendar.getInstance();
        calendar.setTime(date);
        return calendar;
    }



    /**
     *  获取当前月份的第一天
     * @return
     */
    public static String getCurFirstDayOfMonth(String formatStr) {
        Calendar calendar = Calendar.getInstance();

        calendar.set(Calendar.DAY_OF_MONTH, 1);
        DateFormat format = new SimpleDateFormat(formatStr);
        return format.format(calendar.getTime()).trim();
    }


    /**
     *  获取当前月份的最后一天
     * @return
     */
    public static String getCurLastDayOfMonth(String formatStr) {
        Calendar calendar = Calendar.getInstance();

        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));
        DateFormat format = new SimpleDateFormat(formatStr);
        return format.format(calendar.getTime()).trim();
    }


    /**
     *  获取当前月份的上一个月的第一天
     * @return
     */
    public static String getCurPreviousFirstDayOfMonth(String formatStr) {
        Calendar calendar = Calendar.getInstance();

        calendar.add(Calendar.MONTH, -1);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        DateFormat format = new SimpleDateFormat(formatStr);
        return format.format(calendar.getTime()).trim();
    }


    /**
     *  获取当前月份的上一个月的最后一天
     * @return
     */
    public static String getCurPreviousLastDayOfMonth(String formatStr) {
        Calendar calendar = Calendar.getInstance();

        calendar.set(Calendar.DAY_OF_MONTH, 0);
        DateFormat format = new SimpleDateFormat(formatStr);
        return format.format(calendar.getTime()).trim();
    }


    /**
     *  获取指定月份的上一个月的最后一天
     * @return
     */
    public static String getPointPreviousLastDayOfMonth(String dateStr, String formatStr) throws ParseException{
        SimpleDateFormat format=new SimpleDateFormat(formatStr);
        Date date=format.parse(dateStr);

        Calendar calendar=Calendar.getInstance();
        calendar.setTime(date);

        calendar.set(Calendar.DAY_OF_MONTH, 0);
        return format.format(calendar.getTime()).trim();
    }


    /**
     *  获取指定时间的下一个月的第一天
     * @return
     */
    public static String getPointNextFirstDayOfMonth(String dateStr, String formatStr) throws Exception{
        String pointEndDay = getPointLastDayOfMonth(dateStr, "yyyy-MM-dd");// 获取指定时间所在月份的最后一天

        SimpleDateFormat format=new SimpleDateFormat(formatStr);
        Calendar calendar = str2Calendar(pointEndDay,formatStr);
        calendar.set(Calendar.DAY_OF_MONTH, 1);

        calendar.add(Calendar.MONTH, 1);
        return format.format(calendar.getTime()).trim();
    }


    /**
     *  获取指定时间的下一个月的最后一天
     * @return
     */
    public static String getPointNextLastDayOfMonth(String dateStr, String formatStr) throws Exception{
        String nextFirstDay = getPointNextFirstDayOfMonth(dateStr, formatStr);
        return getPointLastDayOfMonth(nextFirstDay, formatStr);
    }

    /**
     * 比较startDay日期是否早于endDay
     * @param startDay
     * @param endDay
     * @return
     */
    public static Boolean isBefore(String startDay, String endDay, String formatStr) throws Exception{
        DateFormat dateFormat = new SimpleDateFormat(formatStr);
        Date start = dateFormat.parse(startDay);
        Date end = dateFormat.parse(endDay);
        return start.before(end);
    }

    /**
     * 比较startDay日期是否早于(包括等于)endDay
     * @param startDay
     * @param endDay
     * @return
     */
    public static Boolean isBeforeAndEqu(String startDay, String endDay, String formatStr) throws Exception{
        DateFormat dateFormat = new SimpleDateFormat(formatStr);
        Date start = dateFormat.parse(startDay);
        Date end = dateFormat.parse(endDay);
        return start.before(end) || start.equals(end);
    }



    /**
     * 获取2个日期之间的所有日期
     * @param startDay
     * @param endDay
     * @return
     */
    public static List<String> getBetweenDays(String startDay, String endDay) {
        // 返回的日期集合
        List<String> days = new ArrayList<String>();

        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date start = dateFormat.parse(startDay);
            Date end = dateFormat.parse(endDay);

            Calendar tempStart = Calendar.getInstance();
            tempStart.setTime(start);

            Calendar tempEnd = Calendar.getInstance();
            tempEnd.setTime(end);
            tempEnd.add(Calendar.DATE, +1);// 日期加1(包含结束)
            while (tempStart.before(tempEnd)) {
                days.add(dateFormat.format(tempStart.getTime()));
                tempStart.add(Calendar.DAY_OF_YEAR, 1);
            }

        } catch (ParseException e) {
            throw new RuntimeException("执行失败："+ e);
        }
        return days;
    }


    /**
     * 获取2个日期之间的所有日期【每个月只有一个日期（每月最后一天）】
     * @param startDay
     * @param endDay
     * @return
     */
    public static List<String> getBetweenDayOfMonth(String startDay, String endDay) throws Exception{
        // 返回的日期集合
        List<String> days = new ArrayList<String>();

        try {
            // 判断startDay是否为某个月的最后一天
            String ckStartDay = getPointLastDayOfMonth(startDay, "yyyy-MM-dd");
            if(!StringUtils.equals(startDay, ckStartDay)){
                throw new RuntimeException(startDay + "不是这个月的最后一天");
            }
            // 判断endDay是否为某个月的最后一天
            String ckEndDay = getPointLastDayOfMonth(endDay, "yyyy-MM-dd");
            if(!StringUtils.equals(endDay, ckEndDay)){
                throw new RuntimeException(endDay + "不是这个月的最后一天");
            }
            days.add(startDay);

            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            Date start = dateFormat.parse(startDay);
            Date end = dateFormat.parse(endDay);

            while (start.before(end)){
                String nextLastDayOfMonth = getPointNextLastDayOfMonth(startDay, "yyyy-MM-dd");
                days.add(nextLastDayOfMonth);
                start = dateFormat.parse(nextLastDayOfMonth);
                startDay = nextLastDayOfMonth;
            }

        } catch (Exception e) {
            throw new Exception("执行失败："+ e);
        }
        return days;
    }


    public static String getFormatTime(Date date,String formatStr){
        SimpleDateFormat format = new SimpleDateFormat(formatStr);
        String dateStr = format.format(date);
        return dateStr;
    }

    /**
     * 由时间戳转化为时间字符串
     * @param times
     * @return
     */
    public static String getDateTimeStr(long times){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateStr = format.format(new Date(times));
        return dateStr;
    }




    /**
     *
     * @param date 输入日期，格式为"yyyy-MM-dd"
     * @param formatStr 最终转换日期格式
     * @return
     * @throws ParseException
     */
    public static String getFormatTime(String date,String formatStr) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");//yyyy-mm-dd, 会出现时间不对, 因为小写的mm是代表: 秒
        Date utilDate = sdf.parse(date);

        SimpleDateFormat format = new SimpleDateFormat(formatStr);
        String dateStr = format.format(utilDate);
        return dateStr;
    }

    /**
     * 计算消耗时长（单位自动转换）
     * @param startTime  开始时间
     * @return
     */
    public static String getUsedTimeFormat(Long startTime){
        StringBuilder result = new StringBuilder();
        long usedTime = getUsedTimeByS(startTime);
        if(usedTime<=60){
            result.append(usedTime).append("秒");
        }else if(usedTime<=3600){
            result.append(usedTime/60).append("分").append(usedTime%60).append("秒");
        }else{
            result.append(usedTime/3600).append("小时").append(usedTime%3600/60).append("分").append(usedTime%3600%60).append("秒");
        }
        return result.toString();
    }
    /**
     * 计算消耗时长(单位：秒)
     * @param startTime  开始时间
     * @return
     */
    public static long getUsedTimeByS(Long startTime){
        return (System.currentTimeMillis() - startTime)/1000;
    }

    /**
     * 计算消耗时长,保留小数位(单位：秒)
     * @param startTime  开始时间
     * @return
     */
    public static double getUsedTimeBySrDouble(Long startTime){
        return (double)(System.currentTimeMillis() - startTime)/1000;
    }

    /**
     * 判断 日期时间格式化字符串 是否合法
     *
     * @param formatStr
     * @return
     */
    public static Boolean isLegalOfFormat(String formatStr){
        try {
            DateTimeFormatter format = DateTimeFormatter.ofPattern(formatStr);
            LocalDateTime.now().format(format);
            return true;
        }catch (Exception e){
            return false;
        }
    }


    public static void main(String[] args) {
        System.out.println(isLegalOfFormat("yyyy-Mv"));
        /*System.out.println(getCurrentTimeByUnion());
        System.out.println(getCurrentTime());
        System.out.println(getToday());
        System.out.println(getYesterday());

        Date date = new Date();
        System.out.println(getFormatTime(getThisWeekMonday(date),"yyyyMMdd"));
        System.out.println(getFormatTime(getLastWeekMonday(date),"yyyyMMdd"));
        System.out.println(getFormatTime(getLastWeekSunday(date),"yyyyMMdd"));*/
//        System.out.println(getToday());
//        System.out.println(getYesterday());
//
//        Calendar calendar = Calendar.getInstance();
//        calendar.set(2020,0,7); //月份从0开始
//        Date date2 = calendar.getTime();
//        System.out.println(date2);
//        String lastMonday = DmpDateTimeUtil.getFormatTime(DmpDateTimeUtil.getLastWeekMonday(date2),"yyyyMMdd");
//        String lastSunday = DmpDateTimeUtil.getFormatTime(DmpDateTimeUtil.getLastWeekSunday(date2),"yyyyMMdd");
//        System.out.println(lastMonday);
//        System.out.println(lastSunday);
//
//        date2.setTime(Long.parseLong("79808798"));
//        Calendar c = Calendar.getInstance();
//        c.setTime(date2);
//        System.out.println(getFormatTime(date2,"yyyyMMdd"));

//        System.out.println(getLastDayOfMonth("2020","09"));
//        System.out.println(getFirstDayOfMonth("2020","09"));
//
//        Calendar calendar = Calendar.getInstance(); // 子类对象
//        int year = calendar.get(Calendar.YEAR);
//        int month = calendar.get(Calendar.MONTH)-1;
//        System.out.println(year+":"+month);
//        System.out.println(getFirstDayOfMonth(year+"",month+"","yyyyMMdd"));
//        System.out.println(getLastDayOfMonth(year+"",month+"","yyyyMMdd"));
//        System.out.println(getLastDayOfMonth(year+"",month+"","yyyyMM"));

        try {
            //System.out.println(getFormatTime("2020-03-22","yyyyMMdd"));
            //System.out.println(getBetweenDays("2020-02-27","2020-03-05"));
            //System.out.println(getMillSecondTimeStr());
            //System.out.println(getDateTimeStr(System.currentTimeMillis()));
//            System.out.println(getCurFirstDayOfMonth("yyyy-MM-dd"));
//            System.out.println(getCurLastDayOfMonth("yyyy-MM-dd"));
//            System.out.println(getCurPreviousFirstDayOfMonth("yyyy-MM-dd"));
//            System.out.println(getCurPreviousLastDayOfMonth("yyyy-MM-dd"));
//            System.out.println(getPointLastDayOfMonth("2020-7-3", "yyyy-MM-dd"));
//            System.out.println(getBetweenDayOfMonth("2020-01-31", "2020-04-30"));
//            System.out.println(getPointPreviousLastDayOfMonth("2020-01-22","yyyy-MM-dd"));
//            System.out.println(getBetweenDayOfMonth("2020-01-31", "2020-04-30"));
//            System.out.println(getPointNextLastDayOfMonth("2020-7-3", "yyyy-MM-dd"));
//            System.out.println(isBefore("2020-10-01", "2020-10-01", "yyyy-MM-dd"));
//            System.out.println(isBeforeAndEqu("2020-10-01", "2020-10-01", "yyyy-MM-dd"));
//            System.out.println(getCurYearMonth("yyyyMM"));


        }catch (Exception e){

        }

    }

}
